package com.igoal.service;

import java.util.Date;
import java.util.List;
import java.util.Set;

import org.springframework.transaction.annotation.Transactional;

import com.igoal.dto.GoalDTO;
import com.igoal.dto.UserDTO;
import com.igoal.entity.Goal;
import com.igoal.entity.GoalStatusEnum;

public interface GoalManager extends GenericManager<Goal, Long> {
	/**
	 * Get top 30 goals
	 * 
	 * @param user
	 *            the current session user. Maybe use the user information to
	 *            choose the suitable goals
	 * @return list of {@link GoalDTO}
	 */
	List<GoalDTO> getCommonGoals(UserDTO user);
	
	/**
	 * Get top goals
	 * @param user
	 * @param numberOfGoal
	 * @return
	 */
	List<GoalDTO> getCommonGoals(UserDTO user, int numberOfGoal);

	/**
	 * Get top 10 goals
	 * 
	 * @param user
	 *            the current session user. Maybe use the user information to
	 *            choose the suitable goals
	 * @return list of {@link GoalDTO}
	 */
	List<GoalDTO> getTopGoals(UserDTO user);

	/**
	 * Get goal entity by primary key
	 * 
	 * @param id
	 *            goal pk
	 * @return {@link GoalDTO} entity
	 */
	GoalDTO getGoalByPrimaryKey(Long id);

	/**
	 * Count the number of users who do/finish a goal
	 * 
	 * @param goalId
	 * @return
	 */
	@Transactional(readOnly = true)
	int countDoUsers(Long goalId);
	
	@Transactional(readOnly = true)
	int countDoingUsers(Long goalId);
	
	@Transactional(readOnly = true)
	int countDoneUsers(Long goalId);
	
	/**
	 * Get random users who do/finish a goal
	 * 
	 * @param goalId
	 * @return
	 */
	@Transactional(readOnly = true)
	List<UserDTO> getRandomUsersDoGoal(Long goalId);
	
	/**
	 * Get users who do/finish a goal by page
	 * 
	 * @param goalId
	 * @param pageNumber
	 * @return
	 */
	@Transactional(readOnly = true)
	List<UserDTO> getUsersDoGoal(Long goalId, int pageNumber);

	/**
	 * Add a goal to a category
	 * 
	 * @param goalId
	 * @param categoryId
	 * @return {@link SaveResult}
	 */
	@Transactional(readOnly = false)
	int addGoalToCategory(Long goalId, Long categoryId);

	/**
	 * Add a goal to a category. If the category is not exists, it will be
	 * created
	 * 
	 * @param goalId
	 * @param category
	 *            category name
	 * @return {@link SaveResult}
	 */
	@Transactional(readOnly = false)
	int addGoalToCategory(Long goalId, String category);
	
	/**
	 * Create new category for goal
	 * @param category category name
	 * @return {@link SaveResult}
	 */
	@Transactional(readOnly = false)
	int createNewCategory(String category);

	/**
	 * Check get goal status for the current user
	 * 
	 * @param goalId
	 * @return
	 */
	@Transactional(readOnly = true)
	GoalStatusEnum getGoalStatus(Long goalId);
	
	/**
	 * Find all goals have title like <code>title</code> and in USING
	 * @param title goal title
	 * @return list {@link GoalDTO}
	 */
	@Transactional(readOnly = true)
	List<GoalDTO> findGoalByTitle(String title);
	
	/**
	 * Suggest user a should go goal list
	 * @param userId user identifier, try to find goals that approximately suits with user categories
	 * @return List {@link GoalDTO}
	 */
	@Transactional(readOnly = true)	
	List<GoalDTO> getShouldDoGoals(Long userId);
	
	/**
	 * Find goal by exacted title
	 * @param title goal title
	 * @return null if cannot find
	 */
	@Transactional(readOnly = true)
	GoalDTO getGoalByTitle(String title);
	
	@Transactional(readOnly = true)
	GoalDTO getMustDoGoal(String username);
	
	@Transactional(readOnly = true)
	List<GoalDTO> getAllGoals();
	
	@Transactional(readOnly = false)
	int disable(Long id);
	
	@Transactional(readOnly = false)
	int enable(Long id);
	
	@Transactional(readOnly = true)
	int countGoalsFrom(Date date);
	
	@Transactional(readOnly = true)
	Set<GoalDTO> getRandomGoals(int maxGoals);
}
